package com.lovegu.one;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;

/**
 * <p>
 * 实现发送、嗅探、解析和伪造网络数据包
 * </p>
 *
 * @author 老顾
 * @since 2023/3/29
 */
public class NetworkTools {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        while (true) {
            System.out.println("请选择功能：");
            System.out.println("1. 发送网络数据包");
            System.out.println("2. 嗅探网络数据包");
            System.out.println("3. 解析网络数据包");
            System.out.println("4. 伪造网络数据包");
            System.out.println("0. 退出程序");
            int choice = scanner.nextInt();
            switch (choice) {
                case 0:
                    System.exit(0);
                case 1:
                    sendPacket(scanner);
                    break;
                case 2:
                    sniffPacket(scanner);
                    break;
                case 3:
                    parsePacket(scanner);
                    break;
                case 4:
                    forgePacket(scanner);
                    break;
                default:
                    System.out.println("无效的选项，请重新选择！");
            }
        }
    }

    /**
     * 发送数据包
     *
     * @param scanner 输入缓冲区
     */
    private static void sendPacket(Scanner scanner) {
        try {
            System.out.println("请输入目标IP地址：");
            String destIP = scanner.next();
            System.out.println("请输入目标端口号：");
            int destPort = scanner.nextInt();
            System.out.println("请输入发送内容：");
            String message = scanner.next();

            DatagramSocket socket = new DatagramSocket();
            byte[] buffer = message.getBytes();
            DatagramPacket packet = new DatagramPacket(buffer, buffer.length, InetAddress.getByName(destIP), destPort);
            socket.send(packet);

            System.out.println("发送成功！");
        } catch (IOException e) {
            System.out.println("发送失败：" + e.getMessage());
        }
    }

    /**
     * 嗅探数据包
     *
     * @param scanner 输入缓冲区
     */
    private static void sniffPacket(Scanner scanner) {
        try {
            System.out.println("请输入监听端口号：");
            int listenPort = scanner.nextInt();

            DatagramSocket socket = new DatagramSocket(listenPort);
            byte[] buffer = new byte[1024];
            DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

            System.out.println("开始监听...");
            while (true) {
                socket.receive(packet);
                String message = new String(packet.getData(), 0, packet.getLength());
                System.out.println("收到来自 " + packet.getAddress().getHostAddress() + ":" + packet.getPort() + " 的数据：" + message);
            }
        } catch (IOException e) {
            System.out.println("监听失败：" + e.getMessage());
        }
    }

    /**
     * 解析数据包
     *
     * @param scanner 输入缓冲区
     */
    private static void parsePacket(Scanner scanner) {
        try {
            System.out.println("请输入待解析的数据包内容：");
            String message = scanner.next();

            byte[] buffer = message.getBytes();
            DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
            InetAddress address = packet.getAddress();
            int port = packet.getPort();

            System.out.println("数据包来源：" + address.getHostAddress() + ":" + port);
            System.out.println("数据包内容：" + message);
        } catch (Exception e) {
            System.out.println("解析失败：" + e.getMessage());
        }
    }

    /**
     * 伪造数据包
     *
     * @param scanner 输入缓冲区
     */
    private static void forgePacket(Scanner scanner) {
        try {
            System.out.println("请输入目标IP地址：");
            String destIP = scanner.next();
            System.out.println("请输入目标端口号：");
            int destPort = scanner.nextInt();
            System.out.println("请输入伪造的源IP地址：");
            String srcIP = scanner.next();
            System.out.println("请输入伪造的源端口号：");
            int srcPort = scanner.nextInt();
            System.out.println("请输入伪造的数据包内容：");
            String message = scanner.next();

            DatagramSocket socket = new DatagramSocket();
            byte[] buffer = message.getBytes();
            DatagramPacket packet = new DatagramPacket(buffer, buffer.length, InetAddress.getByName(destIP), destPort);
            packet.setAddress(InetAddress.getByName(srcIP));
            packet.setPort(srcPort);
            socket.send(packet);

            System.out.println("伪造成功！");
        } catch (IOException e) {
            System.out.println("伪造失败：" + e.getMessage());
        }
    }
}
